import { _decorator } from "cc";
import { DataProxy } from "../A-LIB/lib.b.data";
import { UI } from "./ui.origin";

const {ccclass, property} = _decorator;

@ccclass
export abstract class BaseUI extends UI{
    protected __listen_list__: ReturnType<typeof this.listening> = [];

    /** 注册监听 */
    protected listening(): ReturnType<typeof DataProxy.follow>[] {return []};
    /** 取消监听 */
    protected closeListen(){
        this.__listen_list__.forEach(reg=>DataProxy.cancel(reg));
		mtec.array.clear(this.__listen_list__);
    };

    protected onLoad(): void {
		this.__ui_loaded = false;
        super.onLoad();
        this.__listen_list__ = this.listening();
        this.__ui_loaded = true;
        this.call_cache.forEach(el=>{
            let [func, param, np] = el;
			np.resolve(Reflect.apply(func, this, param));
        });
		mtec.array.clear(this.call_cache);
    }

    protected onDestroy(){
        this.closeListen();
    }

	private __ui_loaded: boolean;
	/** ui加载状态 */
    protected get ui_loaded(){
		return this.__ui_loaded;
	};
    private call_cache: [Function, any[], mtec.NudityPromise<any>][] = [];
    protected call_func<F extends (...param: any)=>any, R extends ReturnType<F>>(func: F, ...param: Parameters<F>): R|Promise<R>{
        if(this.ui_loaded) return Reflect.apply(func, this, param);
        else{
			let np = new mtec.NudityPromise<R>();
			this.call_cache.push([func, param, np]);
			return np.promise;
		}
    }

	private __late_call_list__: Array<[Function, any[], Function]> = [];
	protected lateUpdate(dt: number): void {
		if(this.__late_call_list__.length>0){
			let [call, args, complete] = this.__late_call_list__.pop();
			typeof complete=='function' ? complete(call(...args), args) : call(...args);
		}
	}

	/**
	 * 在帧后执行回调
	 * @param call
	 * @param args
	 * @param complete
	 */
	protected frameLateCall<C extends (...args: any[])=>any, Param extends Parameters<C>, R extends ReturnType<C>>(call: C, args: Param, complete?: (r: R, args: Param)=>void){
		this.__late_call_list__.unshift([call, args, complete]);
	}

	/**
	 * 帧循环
	 * @param list
	 * @param call
	 * @returns
	 */
	protected frameWhile<T extends any[]>(list: T, call: (el: T[number], index: number, arr: T)=>void){
		return new Promise<0>(s=>list.forEach((e, i, a)=>this.frameLateCall(call, [e, i, list], (_, [e, i, a])=>i==list.length-1 ? s(0) : void 0)));
	}

	protected follow = DataProxy.follow;

	protected hasFollow = DataProxy.hasFollow;

	protected cancel = DataProxy.cancel;

	protected outFollow = DataProxy.out;

	protected monitor = DataProxy.monitor;

	protected freeMonitor = DataProxy.free;

	protected revokeProxy = DataProxy.revoke;

	protected proxy = DataProxy.proxy;

	protected hasProxy = DataProxy.hasProxy;
}